
var SelfBrowser = {};

(function () {

    var rootURL = decodeURIComponent(window.location.hash.substr(1));

    var domainFavicons = {
        'livejournal.com': true,
        'last.fm': true,
        'myspace.com': true,
        'digg.com': true,
        'facebook.com': true,
        'linkedin.com': 'http://www.linkedin.com/favicon.ico',
        'jaiku.com': true,
        'meetup.com': true,
        'tribe.net': true,
        'youtube.com': true,
        'orkut.com': true,
        'aol.com': true,
        'reddit.com': true,
        'twitter.com': true,
        'del.icio.us': true,
        'ma.gnolia.com': true,
        'zooomr.com': true,
        'picasaweb.google.com': true,
        'amazon.com': true,
        'dopplr.com': true,
        'upcoming.yahoo.com': true,
        'bloglines.com': true,
        'yelp.com': true
    };

    var rootNode = undefined;
    var requestIdx = 0;

    var friendsListStore = undefined;
    var friendsListStoreFields = [ "id", "edgeTypesString", "displayName", "photoURL", "otherNames" ];
    var metaNodeMembersStore = undefined;
    var metaNodeMembersStoreFields = [ "url", "displayName", "iconURL", "connectionDescriptions", "connectionTypes" ];

    var begin = function () {
        if (rootURL) {

            if (friendsListStore) {
                friendsListStore.removeAll();
            }
            if (metaNodeMembersStore) {
                metaNodeMembersStore.removeAll();
            }

            var thisRequestIdx = ++requestIdx;
            document.title = "It's Who You Know!";
            SocialGraph.fetchNode(rootURL, function (node) {
                if (thisRequestIdx != requestIdx) {
                    // A response has come in from a cancelled request,
                    // so we just throw the results away.
                    return;
                }

                var metaNode = node.getMetaNode();
                if (setRootURL) {
                    setRootURL(node.getIdentifier());
                }
                document.title = "It's Who You Know! ("+node.getIdentifier()+")";
                rootNode = node;

                var rootMetaNode = node.getMetaNode();
                rootMetaNode.fetchReferencedMetaNodes(function (references) {

                    var FriendsListRecord = Ext.data.Record.create(friendsListStoreFields);

                    for (var i = 0; i < references.length; i++) {
                        var metaNode = references[i][0];
                        var edgeTypes = references[i][1];

                        if (metaNode) {
                            var names = metaNode.getFullNames();
                            var usernames = metaNode.getUsernames();
                            var urls = metaNode.getNodeURLs();
                            var photos = metaNode.getValuesForAttribute("photo");

                            var mainName = names.shift();
                            if (! mainName) {
                                mainName = usernames.shift();
                            }
                            if (! mainName) {
                                mainName = urls.shift();
                            }

                            if (friendsListStore) {
                                friendsListStore.add(new FriendsListRecord({
                                    id: metaNode.getIndex(),
                                    displayName: mainName,
                                    edgeTypesString: edgeTypes.join(" "),
                                    photoURL: photos.shift(),
                                    otherNames: ''
                                }));
                            }
                        }
                        else {
                            console.log("We seem to have an undefined metaNode");
                        }
                    }
                });

            });
        }
    };

    var currentSelectedMetaNode = null;
    var metaNodeRequestIndex = 0;

    var showMetaNodeDetail = function (metaNode) {
        var ProfilesRecord = Ext.data.Record.create(metaNodeMembersStoreFields);

        if (metaNodeMembersStore) {
            metaNodeMembersStore.removeAll();
            currentSelectedMetaNode = metaNode.getIndex();
            var requestIndex = ++metaNodeRequestIndex;
            metaNode.fetchNodes(function (nodes) {
                if (requestIndex == metaNodeRequestIndex) {
                    for (var i = 0; i < nodes.length; i++) {
                        var node = nodes[i];
                        var iconURL = '';

                        var sgnDomain = node.getSGNDomain();
                        if (sgnDomain == "mboxsha1") continue;
                        if (sgnDomain) {
                            var iconURL = domainFavicons[sgnDomain] ? domainFavicons[sgnDomain] : '';
                            if (iconURL === true) iconURL = 'http://'+sgnDomain+'/favicon.ico';
                        }
                        if (! iconURL) iconURL = "other.png";

                        var displayName = node.getIdentifier();
                        if (node.getSGNPK()) displayName = "#"+node.getSGNPK();
                        if (node.getUsername()) displayName = node.getUsername();
                        if (sgnDomain) displayName += " at "+sgnDomain;

                        var connectionDescriptions = [];
                        var connectionTypesString = '';

                        if (rootNode) {
                            var rootMetaNode = rootNode.getMetaNode();
                            if (rootMetaNode) {
                                var connections = rootMetaNode.getReferencesToNode(node);
                                for (var j = 0; j < connections.length; j++) {
                                    var connectionTypes = connections[j][0];
                                    var connectionNode = connections[j][1];
                                    connectionTypesString = connectionTypes.join(" ");

                                    var whatStringBits = [];
                                    var viaString = connectionNode.getIdentifier();
                                    if (connectionNode.getSGNDomain()) viaString = connectionNode.getSGNDomain();
                                    var numberOfConnectionTypes = connectionTypes.length;
                                    for (var k = 0; k < numberOfConnectionTypes; k++) {
                                        if (k == 0) {
                                            // Nothing
                                        }
                                        else if (k == numberOfConnectionTypes - 1) {
                                            whatStringBits.push(" and ");
                                        }
                                        else {
                                            whatStringBits.push(", ");
                                        }
                                        whatStringBits.push(connectionTypes[k]);
                                    }

                                    connectionDescriptions.push(['<strong>', whatStringBits.join(""), "</strong> via ", viaString].join(""));

                                }
                                if (connectionDescriptions.length == 0) {
                                    connectionDescriptions.push("No connection!");
                                }
                                if (connectionTypesString == '') {
                                    connectionTypesString = 'unconnected';
                                }
                            }
                        }

                        if ((i % 2) == 1) {
                            connectionTypesString += " even";
                        }

                        var links = [];

                        var profileURL;
                        var mainURL;

                        if (sgnDomain) {
                            profileURL = node.getAttributeByName("profile");
                            mainURL = node.getAttributeByName("url");
                        }
                        else {
                            mainURL = node.getIdentifier();
                            profileURL = undefined;
                        }

                        if (mainURL && mainURL != profileURL) {
                            links.push({
                                caption: "View",
                                url: mainURL
                            });
                        }
                        if (profileURL) {
                            links.push({
                                caption: "Profile",
                                url: profileURL
                            });
                        }

                        console.log("Profile is ", profileURL);

                        links.push({
                            caption: 'Browse',
                            url: '#'+encodeURIComponent(node.getIdentifier())
                        });

                        metaNodeMembersStore.add(new ProfilesRecord({
                            url: node.getIdentifier(),
                            displayName: displayName,
                            iconURL: iconURL,
                            connectionDescriptions: connectionDescriptions.join(", "),
                            connectionTypes: connectionTypesString,
                            links: links
                        }));
                    }
                }
                else {
                    // This is a response to a stale request. Ignore.
                    return;
                }
            });
        }

    };

    var setRootURL;

    // Poll the URL fragment identifier so that if the user changes it,
    // or if they follow a link, we can react.
    window.setInterval(function () {
        var newRootURL = decodeURIComponent(window.location.hash.substr(1));
        if (newRootURL != rootURL) {
            if (setRootURL) {
                setRootURL(newRootURL);
            }
            rootURL = newRootURL;
            begin();
        }
    }, 500);

    Ext.onReady(function () {

        var toolbarConfig = {
            id: 'header',
            region: 'north',
            autoHeight: true,
            border: false
        };
        var toolbar = new Ext.Toolbar(toolbarConfig);

        var statusBarConfig = {
            id: 'statusbar',
            region: 'south',
            xtype: 'statusbar',
            defaultIconCls: '',
            defaultText: ''
        };
        var statusBar = new Ext.StatusBar(statusBarConfig);

        friendsListStore = new Ext.data.SimpleStore({
            data: [],
            fields: friendsListStoreFields,
            id: "id"
        });

        var friendsListTemplate = new Ext.XTemplate(
            '<tpl for=".">',
            '<div class="friendsummary {edgeTypesString}" id="friendsummary_{id}"><div class="friendthumbnailcontainer">',
            '<tpl if="photoURL">',
            '<img src="{photoURL}" onload="SelfBrowser.prepareFriendThumbnail(this)" class="friendthumbnail" style="opacity:0"/>',
            '</tpl>',
            '</div>{displayName}</div>',
            '</tpl>'
        );

        var westConfig = {
            xtype: "dataview",
            store: friendsListStore,
            tpl: friendsListTemplate,
            emptyText: 'Nothing to display',
            itemSelector: '.friendsummary',
            autoHeight: true,
            region: 'center',
            title: 'friends',
            singleSelect: true
        };
        var west = new Ext.DataView(westConfig);
        west.on("selectionchange", function (dataView, selections) {
            var selection = selections[0];
            var record = selection ? dataView.getRecord(selection) : null;

            if (record) {
                id = record.data.id;
                metaNode = SocialGraph.getMetaNode(id);
                showMetaNodeDetail(metaNode);
            }
            else {
                // TODO: clear the details list?
            }
        });

        var westContainer = {
            region: "west",
            xtype: "panel",
            title: "",
            border: true,
            autoScroll: true,
            items: west,
            width: 200
        };

        metaNodeMembersStore = new Ext.data.SimpleStore({
            data: [],
            fields: metaNodeMembersStoreFields
        });

        var metaNodeMembersTemplate = new Ext.XTemplate(
            '<tpl for=".">',
            '<div class="profilesummary {connectionTypes}">',
            '<h1>',
            '<tpl if="iconURL"><img src="{iconURL}" width="16" height="16" /></tpl> {displayName}',
            '</h1>',
            '<div class="profilesummarylinks">',
            '<tpl for="links">',
            '<span class="profilesummarylink"><a href="{url}">[{caption}]</a></span>',
            '</tpl>',
            '</div>',
            '<div class="profilesummaryconnections">{connectionDescriptions}</div>',
            '</div>',
            '</tpl>'
        );

        var centerConfig = {
            xtype: "dataview",
            store: metaNodeMembersStore,
            tpl: metaNodeMembersTemplate,
            emptyText: 'Nothing to display',
            itemSelector: '.profilesummary',
            autoHeight: true,
            title: 'friends',
            singleSelect: false
        };
        var center = new Ext.DataView(centerConfig);

        var centerContainer = {
            region: "center",
            xtype: "panel",
            title: "",
            border: false,
            autoScroll: true,
            items: center
        };

        var toolbarContainer = {
            region: "north",
            xtype: "panel",
            title: "",
            items: toolbar,
            border: true,
            height: 31
        };

        var statusBarContainer = {
            region: "south",
            xtype: "panel",
            title: "",
            items: statusBar,
            border: true,
            height: 31
        };

        var viewport = new Ext.Viewport({
            layout: 'border',
            id: 'root',
            border: false,
            items: [ toolbarContainer, westContainer, centerContainer, statusBarContainer ]
        });

        var locationField = new Ext.form.TextField({
            emptyText: "Enter URL",
            width: 400
        });
        toolbar.addField(locationField);

        setRootURL = function (url) {
            rootURL = url;
            if (window.location.hash.substr(1) != url) {
                window.location.hash = encodeURIComponent(url);
            }
            locationField.setValue(url);
            rootNode = undefined;
        };

        var goButton = toolbar.addButton({
            text: "Go"
        });
        var handleGoButton = function () {
            var url = locationField.getValue();
            if (url) {
                setRootURL(url);
                begin();
            }
            else {
                alert("You must enter a URL");
            }
        };
        goButton.on("click", handleGoButton);
        locationField.on("specialkey", function (field, evt) {
            if (evt.getKey() == 13) {
                handleGoButton();
            }
        });

        if (rootURL) {
            locationField.setValue(rootURL);
        }

        // Get SGAPI to tell us when it's doing network stuff
        // so that we can update the status bar.
        SGAPI.setBeginRequestListener(function (urls) {
            // TODO: Do something sensible in the UI
        });
        SGAPI.setEndRequestListener(function (urls) {
            // TODO: Do something sensible in the UI
        });
        SGAPI.setBeginNetworkListener(function () {
            statusBar.showBusy();
        });
        SGAPI.setEndNetworkListener(function () {
            statusBar.clearStatus({useDefaults:true});
        });

        begin();

    });

    SelfBrowser.prepareFriendThumbnail = function (image) {
        var extElem = new Ext.Element(image);
        // Calculate a size that'll make the image fit in the
        // space allocated while retaining the aspect ratio.

        var sourceWidth = image.width;
        var sourceHeight = image.height;
        var maxSize = 50;
        var ourWidth = null;
        var ourHeight = null;
        var aspect = sourceWidth / sourceHeight;

        if (sourceWidth <= maxSize && sourceHeight <= maxSize) {
            // No resizing required!
            ourWidth = sourceWidth;
            ourHeight = sourceHeight;
        }
        else if (sourceWidth >= sourceHeight) {
            // The image is wider than it is tall, or it's square
            ourWidth = maxSize;
            ourHeight = maxSize / aspect;
        }
        else {
            // The image is taller than it is wide
            ourWidth = maxSize * aspect;
            ourHeight = maxSize;
        }

        image.setAttribute("width", ourWidth);
        image.setAttribute("height", ourHeight);

        // Now how much do we need to offset them to center them in the box?
        var x = (maxSize / 2) - (ourWidth / 2);
        var y = (maxSize / 2) - (ourHeight / 2);
        image.style.position = "relative";
        image.style.left = x+"px";
        image.style.top = y+"px";

        extElem.setOpacity(1, true);
    };

})();



